/**************************************************************
* cfg用来设置出厂配置，并对参数进行加密
* cfg set mac=845dd7001122
* cfg set ssid=AirDisk
* cfg set encryption=none(wep,wpa,wpa2,mixed-wpa)
* cfg set password=00000000
* cfg set ip=192.168.222.254
* cfg set dhcp_start=xxx
* cfg set dhcp_end=xxx
* cfg set wpa_cipher=xxx(tkip,aes,tkip/aes)
* 同时，cfg还可以读取配置信息，
* 读取的格式为cfg get xxx
* 得到的参数会打印出来
* Author: liuxiaolong
* time: 2012-12-6
**************************************************************/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "uci_for_cgi.h"

#define Debug_cfg 0
#define ENCODE 0

#define CFG_DEV 		"/dev/mtdblock0"  	//uboot所在的分区
#define CFG_FLAG_ADDR	0x17ff0				//标志位的地址
#define CFG_FLAG		"airdisk"
#define CFG_BASE_ADDR	0x18000  			//32KB的数据空间可用
#define DATA_LEN		32
#define MAC_ADDR		0x1fc00  			//固定的地址，不可改变
#define SSID_ADDR		CFG_BASE_ADDR
#define ENCRYPTION_ADDR	(CFG_BASE_ADDR+DATA_LEN*1)
#define PASSWORD_ADDR	(CFG_BASE_ADDR+DATA_LEN*2)
#define IP_ADDR			(CFG_BASE_ADDR+DATA_LEN*3)
#define DHCP_START_ADDR (CFG_BASE_ADDR+DATA_LEN*4)
#define DHCP_END_ADDR	(CFG_BASE_ADDR+DATA_LEN*5)
#define WPA_CIPHER_ADDR	(CFG_BASE_ADDR+DATA_LEN*6)
//mac ssid encryption password ip dhcp_start dhcp_end wpa_cipher
#define PARA_MAC		"mac"
#define PARA_SSID 		"ssid"
#define PARA_ENCRYPTION	"encryption"
#define PARA_PASSWORD	"password"
#define PARA_IP			"ip"
#define PARA_DHCP_START	"dhcp_start"
#define PARA_DHCP_END	"dhcp_end"
#define PARA_WPA_CIPHER	"wpa_cipher"


static void usage(void)
{
	printf("usage: airdisk config tool\n");
	printf("config parameters are: mac ssid encryption password ip dhcp_start dhcp_end wpa_cipher\n");
	printf("	set 		: cfg set parameter=value \n");
	printf("	get 		: cfg get parameter \n");
	printf("	checkflag 	: check whether config parameters has been set\n");
	printf("	setflag 	: set the flag to mtd\n");
	printf("	clearflag 	: clear the flag from mtd\n");		
	exit(1);
}
//对字符串进行加密，每个字符与0xfe进行异或
static void encode_string(unsigned char *org_str)
{
#if ENCODE
	int org_str_len=strlen(org_str);
	int i=0;
	for(i=0;i<org_str_len;i++)
	{
		org_str[i]=org_str[i]^0xfe;
	}
#else
	;
#endif
}

//解密，同样每个字符与0xfe进行异或
static void decode_string(unsigned char *en_str)
{
#if ENCODE
	int en_str_len=strlen(en_str);
	int i=0;
	for(i=0;i<en_str_len;i++)
	{
		en_str[i]=en_str[i]^0xfe;
	}
#else
	;
#endif
}
static void read_mtd(unsigned char *buffer,FILE *fp,unsigned long offset,unsigned long len)
{
	fseek(fp,offset,SEEK_SET);
	fread(buffer,len,1,fp);
}

static void write_mtd(unsigned char *buffer,FILE *fp,unsigned long offset,unsigned long len)
{
	fseek(fp,offset,SEEK_SET);
	fwrite(buffer,len,1,fp);
}

//检查标志位，如果标志位为airdisk，说明配置参数已经被设置，否则
//则没有被设置
static int check_cfg_flag(int ifprint)
{
	unsigned char cfg_flag[16];
	FILE *fp_mtd;
	fp_mtd=fopen(CFG_DEV,"rb");
	if(fp_mtd==NULL)
	{
		#if Debug_cfg
		printf("open /dev/mtdblock0 failed\n");
		#endif
		exit(1);
	}
	memset(cfg_flag,0,sizeof(cfg_flag));
	read_mtd(cfg_flag,fp_mtd,CFG_FLAG_ADDR,strlen(CFG_FLAG));
	fclose(fp_mtd);
	if(!strcmp((char *)cfg_flag,CFG_FLAG))
	{
		if(ifprint!=1)
			printf(CFG_FLAG);
		return 1;

	}
	else
		return 0;

}
//将标志位设置为airdisk，如果参数被写入，则必须将标志位设为airdisk
static set_cfg_flag()
{
	
	FILE *fp_mtd;
	fp_mtd=fopen(CFG_DEV,"rb+");
	if(fp_mtd==NULL)
	{
		#if Debug_cfg
		printf("open /dev/mtdblock0 failed\n");
		#endif
		exit(1);
	}
	write_mtd(CFG_FLAG,fp_mtd,CFG_FLAG_ADDR,strlen(CFG_FLAG));
	fclose(fp_mtd);
}
//清除标志位
static clear_cfg_flag()
{
	FILE *fp_mtd;
	unsigned char clean_flag[strlen(CFG_FLAG)];
	memset(clean_flag,0xff,strlen(CFG_FLAG));
	fp_mtd=fopen(CFG_DEV,"rb+");
	if(fp_mtd==NULL)
	{
		#if Debug_cfg
		printf("open /dev/mtdblock0 failed\n");
		#endif
		exit(1);
	}
	write_mtd(clean_flag,fp_mtd,CFG_FLAG_ADDR,strlen(CFG_FLAG));
	fclose(fp_mtd);
}
//检查mac地址是否合法
static int check_mac(char *mac_addr)
{
	int i=0;
	if(strlen(mac_addr)!=12)
	{
		#if Debug_cfg
		printf("the mac address must be 12 charactors\n");
		#endif
		return 1;
	}
	for(i=0;i<12;i++)
	{
		if(!isxdigit(mac_addr[i]))
		{
			#if Debug_cfg
			printf("wrong charactor\n");
			#endif
			return 1;
		}

	}
	return 0;
}

//获取参数
int cfg_get(char *argv[])
{
	FILE *fp_mtd;
	fp_mtd=fopen(CFG_DEV,"rb");
	if(fp_mtd==NULL)
	{
		#if Debug_cfg
		printf("open /dev/mtdblock0 failed\n");
		#endif
		exit(1);
	}
	if(!strcmp(argv[2],PARA_MAC))
	{
		unsigned char mac[DATA_LEN];  //必须为unsigned char,不能定义为char，mac地址的范围为00-ff
		memset(mac,0,sizeof(mac));
		read_mtd(mac,fp_mtd,MAC_ADDR,6);
		//decode_string(mac);
		printf("%s=%02x%02x%02x%02x%02x%02x",PARA_MAC,mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);
		//printf("%s",(char *)mac);
		printf("\n");
		
	}
	else if(!strcmp(argv[2],PARA_SSID))
	{
		unsigned char ssid[DATA_LEN];
		memset(ssid,0,sizeof(ssid));
		read_mtd(ssid,fp_mtd,SSID_ADDR,DATA_LEN);
		decode_string(ssid);
		if(strstr(ssid,PARA_SSID)!=NULL)
		{
			printf("%s",(char *)ssid);
			printf("\n");
		}
	}
	else if(!strcmp(argv[2],PARA_ENCRYPTION))
	{
		unsigned char encryption[DATA_LEN];
		memset(encryption,0,sizeof(encryption));
		read_mtd(encryption,fp_mtd,ENCRYPTION_ADDR,DATA_LEN);
		decode_string(encryption);
		if(strstr(encryption,PARA_ENCRYPTION)!=NULL)
		{
			printf("%s",(char *)encryption);
			printf("\n");
		}
	}
	else if(!strcmp(argv[2],PARA_PASSWORD))
	{
		unsigned char password[DATA_LEN];
		memset(password,0,sizeof(password));
		read_mtd(password,fp_mtd,PASSWORD_ADDR,DATA_LEN);
		decode_string(password);
		if(strstr(password,PARA_PASSWORD)!=NULL)
		{
			printf("%s",(char *)password);
			printf("\n");
		}
	}
	else if(!strcmp(argv[2],PARA_IP))
	{
		unsigned char ip[DATA_LEN];
		memset(ip,0,sizeof(ip));
		read_mtd(ip,fp_mtd,IP_ADDR,DATA_LEN);
		decode_string(ip);
		if(strstr(ip,PARA_IP)!=NULL)
		{
			printf("%s",(char *)ip);
			printf("\n");
		}
	}
	else if(!strcmp(argv[2],PARA_DHCP_START))
	{
		unsigned char dhcp_start[DATA_LEN];
		memset(dhcp_start,0,sizeof(dhcp_start));
		read_mtd(dhcp_start,fp_mtd,DHCP_START_ADDR,DATA_LEN);
		decode_string(dhcp_start);
		if(strstr(dhcp_start,PARA_DHCP_START)!=NULL)
		{
			printf("%s",(char *)dhcp_start);
			printf("\n");
		}
	}
	else if(!strcmp(argv[2],PARA_DHCP_END))
	{
		unsigned char dhcp_end[DATA_LEN];
		memset(dhcp_end,0,sizeof(dhcp_end));
		read_mtd(dhcp_end,fp_mtd,DHCP_END_ADDR,DATA_LEN);
		decode_string(dhcp_end);
		if(strstr(dhcp_end,PARA_DHCP_END)!=NULL)
		{
			printf("%s",(char *)dhcp_end);
			printf("\n");
		}
	}
	else if(!strcmp(argv[2],PARA_WPA_CIPHER))
	{
		unsigned char wpa_cipher[DATA_LEN];
		memset(wpa_cipher,0,sizeof(wpa_cipher));
		read_mtd(wpa_cipher,fp_mtd,WPA_CIPHER_ADDR,DATA_LEN);
		decode_string(wpa_cipher);
		if(strstr(wpa_cipher,PARA_WPA_CIPHER)!=NULL)
		{
			printf("%s",(char *)wpa_cipher);
			printf("\n");
		}
	}
	else
	{
		#if Debug_cfg
		printf("invalid parameter!\n");
		#endif
	}
	
	fclose(fp_mtd);
}

//设置参数
int cfg_set(char *argv[])
{
	FILE *fp_mtd;
	unsigned char data_str[32]={0};
	char str_sp[64]="\0";
	char uci_option_str[64]="\0";
	memset(data_str,0,sizeof(data_str));
	fp_mtd=fopen(CFG_DEV,"rb+");
	if(fp_mtd==NULL)
	{
		#if Debug_cfg
		printf("open /dev/mtdblock0 failed\n");
		#endif
		exit(1);
	}
	if(!strncmp(PARA_MAC,argv[2],strlen(PARA_MAC)))
	{
		int i=0;
		char mac_input[32]="\0";
		unsigned char mac_temp[12];
		unsigned char mac[10];
		memset(mac,0,sizeof(mac));
		strcpy(mac_input,argv[2]+strlen(PARA_MAC)+1);
		if(check_mac(mac_input))
		{
			fclose(fp_mtd);
			exit(1);
		}
		for(i=0;i<12;i++)
		{
			if(mac_input[i]>='0' && mac_input[i]<='9')
			{
				mac_temp[i]=mac_input[i]-48;
			}
			else if(mac_input[i]>='a' && mac_input[i]<='f')
			{
				mac_temp[i]=mac_input[i]-97+10;
			}
			else if(mac_input[i]>='A' && mac_input[i]<='F')
			{
				mac_temp[i]=mac_input[i]-65+10;
			}
		}
		for(i=0;i<6;i++)
		{
			mac[i]=mac_temp[2*i]*16 + mac_temp[2*i+1];
		}
		
		//strcpy(data_str,PARA_MAC);
		//strcat(data_str,"=");
		//strcat(data_str,mac);
		//encode_string(data_str);
		write_mtd(mac,fp_mtd,MAC_ADDR,6);
		sprintf(str_sp,"wireless.radio0.macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
						mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);
		uci_set_option_value(str_sp);
		memset(str_sp,0,64);
	}
	else if(!strncmp(PARA_SSID,argv[2],strlen(PARA_SSID))) 
	{
		strcpy(data_str,argv[2]);
		encode_string(data_str);
		write_mtd(data_str,fp_mtd,SSID_ADDR,strlen(data_str)+1);
		memset(data_str,0,sizeof(data_str));
		sprintf(str_sp,"wireless.@wifi-iface[0].ssid=%s",argv[2]+strlen(PARA_SSID)+1);
		uci_set_option_value(str_sp);
		memset(str_sp,0,64);
	}
	else if(!strncmp(PARA_ENCRYPTION,argv[2],strlen(PARA_ENCRYPTION)))  
	{
		char str_encryption[32]="\0";
		strcpy(data_str,argv[2]);
		encode_string(data_str);
		write_mtd(data_str,fp_mtd,ENCRYPTION_ADDR,strlen(data_str)+1);
		memset(data_str,0,sizeof(data_str));
		
		if(!strcmp(argv[2]+strlen(PARA_ENCRYPTION)+1,"0"))
			strcpy(str_encryption,"none");
		else if(!strcmp(argv[2]+strlen(PARA_ENCRYPTION)+1,"1"))
			strcpy(str_encryption,"wep");
		else if(!strcmp(argv[2]+strlen(PARA_ENCRYPTION)+1,"2"))
			strcpy(str_encryption,"psk");
		else if(!strcmp(argv[2]+strlen(PARA_ENCRYPTION)+1,"4"))
			strcpy(str_encryption,"psk2");
		else if(!strcmp(argv[2]+strlen(PARA_ENCRYPTION)+1,"6"))
			strcpy(str_encryption,"mixed-psk");
		
		sprintf(str_sp,"wireless.@wifi-iface[0].encryption=%s",str_encryption);
		uci_set_option_value(str_sp);
		memset(str_sp,0,64);
		
	}
	else if(!strncmp(PARA_PASSWORD,argv[2],strlen(PARA_PASSWORD)))  
	{
		strcpy(data_str,argv[2]);
		encode_string(data_str);
		write_mtd(data_str,fp_mtd,PASSWORD_ADDR,strlen(data_str)+1);
		memset(data_str,0,sizeof(data_str));
		sprintf(str_sp,"wireless.@wifi-iface[0].key=%s",argv[2]+strlen(PARA_PASSWORD)+1);
		uci_set_option_value(str_sp);
		memset(str_sp,0,64);
	}
	else if(!strncmp(PARA_IP,argv[2],strlen(PARA_IP)))  
	{
		char org_ip[32]="\0";
		char set_ip[32]="\0";
		strcpy(set_ip,argv[2]+strlen(PARA_IP)+1);
		
		
		strcpy(uci_option_str,"powertools.@system[0].address");  		
		uci_get_option_value(uci_option_str,org_ip);
		memset(uci_option_str,'\0',64);
		
		strcpy(data_str,argv[2]);
		encode_string(data_str);
		write_mtd(data_str,fp_mtd,IP_ADDR,strlen(data_str)+1);
		memset(data_str,0,sizeof(data_str));
		sprintf(str_sp,"powertools.@system[0].address=%s",argv[2]+strlen(PARA_IP)+1);
		uci_set_option_value(str_sp);
		memset(str_sp,0,64);
		sprintf(str_sp,"network.lan.ipaddr=%s",argv[2]+strlen(PARA_IP)+1);
		uci_set_option_value(str_sp);
		memset(str_sp,0,64);
		
		if( strcmp(org_ip,set_ip)!=0)
		{
			sprintf(str_sp,"sed -e 's/%s/%s/g' -i /etc/hosts",org_ip,set_ip);
			system(str_sp);
			
			memset(str_sp,0,64);
		}
		
		
	}
	else if(!strncmp(PARA_DHCP_START,argv[2],strlen(PARA_DHCP_START)))  //PARA_DHCP_START
	{
		strcpy(data_str,argv[2]);
		encode_string(data_str);
		write_mtd(data_str,fp_mtd,DHCP_START_ADDR,strlen(data_str)+1);
		memset(data_str,0,sizeof(data_str));
		sprintf(str_sp,"dhcp.lan.start=%s",argv[2]+strlen(PARA_DHCP_START)+1);
		uci_set_option_value(str_sp);
		memset(str_sp,0,64);
	}
	else if(!strncmp(PARA_DHCP_END,argv[2],strlen(PARA_DHCP_END))) 
	{
		char start_num[32]="\0";
		char end_num[32]="\0";
		int istart=0;
		int iend=0;
		strcpy(data_str,argv[2]);
		encode_string(data_str);
		write_mtd(data_str,fp_mtd,DHCP_END_ADDR,strlen(data_str)+1);
		memset(data_str,0,sizeof(data_str));
		
		strcpy(uci_option_str,"dhcp.lan.start");  		
		uci_get_option_value(uci_option_str,start_num);
		memset(uci_option_str,'\0',64);
		
		strcpy(end_num,argv[2]+strlen(PARA_DHCP_END)+1);
		istart= atoi(start_num);
		iend=atoi(end_num);
		
		sprintf(str_sp,"dhcp.lan.limit=%d",iend-istart);
		uci_set_option_value(str_sp);
		memset(str_sp,0,64);
	}
	else if(!strncmp(PARA_WPA_CIPHER,argv[2],strlen(PARA_WPA_CIPHER)))  //tkip---1 aes---2 tkip/aes---3
	{
		char str_encryp[32]="\0";
		char str_cipher[32]="\0";
		char tmp_cipher[32]="\0";
		strcpy(data_str,argv[2]);
		encode_string(data_str);
		write_mtd(data_str,fp_mtd,WPA_CIPHER_ADDR,strlen(data_str)+1);
		memset(data_str,0,sizeof(data_str));
		
		strcpy(uci_option_str,"wireless.@wifi-iface[0].encryption");  		
		uci_get_option_value(uci_option_str,str_encryp);
		memset(uci_option_str,'\0',64);
		
		if(!strcmp(argv[2]+strlen(PARA_WPA_CIPHER)+1,"1"))
			strcpy(tmp_cipher,"tkip");
		else if(!strcmp(argv[2]+strlen(PARA_WPA_CIPHER)+1,"2"))
			strcpy(tmp_cipher,"ccmp");
		else if(!strcmp(argv[2]+strlen(PARA_WPA_CIPHER)+1,"3"))
			strcpy(tmp_cipher,"tkip+ccmp");
		
		if(!strcmp(str_encryp,"psk")||!strcmp(str_encryp,"psk2")||!strcmp(str_encryp,"mixed-psk"))
		{
			sprintf(str_sp,"wireless.@wifi-iface[0].encryption=%s+%s",str_encryp,tmp_cipher);
			uci_set_option_value(str_sp);
			memset(str_sp,0,64);
		}

	}
	else
	{
		#if Debug_cfg
		printf("invalid parameter!");
		#endif
	}
	system("uci commit");
	fclose(fp_mtd);
}

int main(int argc,char *argv[])
{
	ctx=uci_alloc_context();
	if(argc < 2 || !strcmp(argv[1],"-h"))
	{
		usage();
		exit(0);
	}
	if(!strcmp(argv[1],"get"))
	{
		//if(check_cfg_flag(1))
			cfg_get(argv);
	}
	else if(!strcmp(argv[1],"set"))
	{
		//set_cfg_flag();
		cfg_set(argv);
		
	}
	else if(!strcmp(argv[1],"checkflag"))
	{
		check_cfg_flag(0);
	}
	else if(!strcmp(argv[1],"setflag"))
	{
		set_cfg_flag();
	}
	else if(!strcmp(argv[1],"clearflag"))
	{
		clear_cfg_flag();
	}
	else
	{
		usage();
	}
	
	uci_free_context(ctx);
	return 0;
}
